#ifndef PROFILER_H
#define PROFILER_H

// enable/disable compiling of profiler macros
#define IRR_PROFILE 0
#define PROFILER_GUI_ID 99999

#include "IrrTypes.h"
#include "rect.h"

#include <map>
#include <string>

namespace irr
{
	class ITimer;
	
	namespace gui 
	{
		class IGUIEnvironment;
	}

struct ProfileData
{
    ProfileData();
    void Reset();

    u32 mGroupId;
    std::string mName;

    u32 mCountCalls;
    u32 mTimeSum;

    u32 mLastTimeStarted;
};

class Profiler
{
public:
    Profiler();
    virtual ~Profiler();

    void SetTimer(irr::ITimer * irrlichtTimer_)         { mIrrTimer = irrlichtTimer_; }

    // set the rectangle used for the display listbox
    void SetDisplayRect(const core::rect<s32> &rect_)   { mDisplayRect = rect_; }

    void Add(u32 id_, u32 groupId_, const std::string &name_);
    void AddGroup(u32 groupId_, const std::string &name_);
    void Start(u32 id_);
    void Stop(u32 id_);
	void Frame();

    void Reset(u32 id_);
    void ResetGroup(u32 groupId_);
    void ResetAll();
    void Show(irr::gui::IGUIEnvironment* env_);        // print current display group on screen
    void Hide(irr::gui::IGUIEnvironment* env_);
    void Print();       // write current display group to wcout
    void PrintAll();    // write all groups to wcout

    void SetDisplayGroup(u32 groupId_);
    void NextDisplayGroup();
    void PreviousDisplayGroup();
    void FirstDisplayGroup();

protected:
    void PrintGroup(u32 groupId_);
    virtual std::string MakeDataString(const ProfileData & data_);
    virtual std::string MakeTitleString();

private:
    irr::ITimer * mIrrTimer;

	irr::core::rect<s32> mDisplayRect;
    u32 mCurrentGroupId;
//    typedef ProfileDataMap std::map<u32, ProfileData>;
    std::map<u32, ProfileData>  mProfileDatas;
    std::map<u32, ProfileData>  mProfileGroups;
	u32							mFramesCount;
};

#if IRR_PROFILE
    //extern Profiler gPROFILER;

    #define PROFILE_ADD(id_, groupId_, name_)   Application::instance()->gPROFILER->Add(id_, groupId_, name_)
    #define PROFILE_ADD_GROUP(groupId_, name_)  Application::instance()->gPROFILER->AddGroup(groupId_, name_)
    #define PROFILE_START(id_)                  Application::instance()->gPROFILER->Start(id_)
    #define PROFILE_STOP(id_)                   Application::instance()->gPROFILER->Stop(id_)
	#define PROFILE_FRAME()						Application::instance()->gPROFILER->Frame()
#else
    #define PROFILE_ADD(id_, groupId_, name_)
    #define PROFILE_ADD_GROUP(groupId_, name_)
    #define PROFILE_START(id_)
    #define PROFILE_STOP(id_)
	#define PROFILE_FRAME()
#endif // IRR_PROFILE

} // namespace irr

#endif // PROFILER_H 